package com.fundcrawler.service;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fundcrawler.entity.ConceptBoard;
import com.fundcrawler.dto.ApiResponse;
import com.fundcrawler.repository.ConceptBoardRepository;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.data.domain.Sort;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class ConceptBoardService {

    private static final String API_URL = "https://push2.eastmoney.com/api/qt/clist/get";
    private static final int PAGE_SIZE = 50;
    private static final ObjectMapper mapper = new ObjectMapper();

    @Autowired
    private ConceptBoardRepository repository;


    public List<ConceptBoard> getAllBoardsSorted(String sortParam) {
        String[] parts = sortParam.split(",");
        String field = parts[0];
        Sort.Direction direction = parts.length > 1 && "desc".equalsIgnoreCase(parts[1])
                ? Sort.Direction.DESC : Sort.Direction.ASC;

        Sort sort = Sort.by(direction, field);
        return repository.findAll(sort);
    }

    public String getLatestTime() {
        return repository.findTopByOrderByCreatedTimeDesc()
                .map(cb -> cb.getCreatedTime().toString())
                .orElse("无数据");
    }

    // 配置 OkHttpClient（单例）
    private final OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .addInterceptor(chain -> {
                Request request = chain.request().newBuilder()
                        .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")
                        .addHeader("Accept", "application/json")
                        .addHeader("Referer", "https://quote.eastmoney.com/")
                        .build();
                return chain.proceed(request);
            })
            .build();

    /**
     * 定时任务：每10分钟拉取一次全部概念板块数据
     */
    @Scheduled(fixedDelay = 600_000) // 10分钟 = 600,000 毫秒
    public void fetchAndSaveAllBoards() {
        log.info("⏰ 开始拉取东方财富概念板块数据...");

        List<ConceptBoard> allBoards = new ArrayList<>();

        try {
            // Step 1: 获取第一页（获取总数量）
            ApiResponse firstPage = fetchPage(1, PAGE_SIZE);
            if (firstPage == null || firstPage.getData() == null || firstPage.getRc() != 0) {
                log.info("❌ API 请求失败: {}" , JSON.toJSONString(firstPage));
                return;
            }

            int total = firstPage.getData().getTotal();
            log.info("📊 总板块数: " + total);

            allBoards.addAll(firstPage.getData().getBoards());

            // Step 2: 获取剩余页
            int totalPages = (total + PAGE_SIZE - 1) / PAGE_SIZE;
            for (int pn = 2; pn <= totalPages; pn++) {
                log.info("➡️  请求第 " + pn + "/" + totalPages + " 页...");
                ApiResponse page = fetchPage(pn, PAGE_SIZE);
                if (page != null && page.getData() != null && !CollectionUtils.isEmpty(page.getData().getBoards())) {
                    allBoards.addAll(page.getData().getBoards());
                }
                Thread.sleep(300); // 避免请求过快
            }

            // Step 3: 保存到 H2
            if (!allBoards.isEmpty()) {
                // 设置入库时间（避免 JPA @PrePersist 在批量插入时性能差）
                LocalDateTime now = LocalDateTime.now();
                allBoards.forEach(board -> board.setCreatedTime(now));

                repository.saveAll(allBoards);
                log.info("✅ 成功保存 " + allBoards.size() + " 条数据到 H2 数据库");
            } else {
                log.info("📭 未获取到有效数据");
            }

        } catch (Exception e) {
            log.info("❌ 数据拉取或保存失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 使用 OkHttp 请求单页数据
     */
    private ApiResponse fetchPage(int pn, int pz) throws IOException, InterruptedException {
        // 动态构建查询参数
        HttpUrl.Builder urlBuilder = HttpUrl.parse(API_URL).newBuilder()
                .addQueryParameter("np", "1")
                .addQueryParameter("fltt", "1")
                .addQueryParameter("invt", "2")
                .addQueryParameter("fs", "m:90+t:3+f:!50")  // 概念板块
                .addQueryParameter("fid", "f3")             // 按涨幅排序
                .addQueryParameter("po", "1")               // 降序
                .addQueryParameter("dect", "1")
                .addQueryParameter("ut", "fa5fd1943c7b386f172d6893dbfba10b")
                .addQueryParameter("wbp2u", "|0|0|0|web")
                .addQueryParameter("fields", "f12,f13,f14,f1,f2,f4,f3,f152,f20,f8,f104,f105,f128,f140,f141,f207,f208,f209,f136,f222")
                .addQueryParameter("pn", String.valueOf(pn))
                .addQueryParameter("pz", String.valueOf(pz))
                .addQueryParameter("_", String.valueOf(System.currentTimeMillis()));

        Request request = new Request.Builder()
                .url(urlBuilder.build())
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                log.info("HTTP " + response.code() + " from page " + pn);
                return null;
            }

            String responseBody = response.body().string();
            return mapper.readValue(responseBody, ApiResponse.class);
        }
    }

    public static void main(String[] args) {
        new ConceptBoardService().fetchAndSaveAllBoards();
    }
}
